
#import "NSStringAdditions.h"

@implementation NSString(Additions)

//
// decode base64
//
- (NSData*)decodeBase64
{
	static char const* base64Table											= "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
	char const* inputChar													= [self UTF8String];
	NSInteger inputLength													= strlen(inputChar);
	NSMutableData* retValue													= [NSMutableData dataWithCapacity:inputLength];
	while(inputLength)
	{
		char iBuf[4]														= {0};
		char oBuf[3]														= {0};
		NSInteger inputParts												= 0;
		for(NSInteger i = 0; i < 4; i ++)
		{
			if(inputLength)
			{
				inputParts													+= 1;
				char v														= *inputChar;
				v															= v < 43 || v > 122 ? 0 : base64Table[v - 43];
				if(v)
					v														= v == '$' ? 0 : v - 61;
				iBuf[i]														= v ? v - 1 : 0;
				inputChar													+= 1;
				inputLength													-= 1;
			}
			else
			{
				iBuf[i]														= 0;
				break;
			}
		}
		
		oBuf[0]																= (iBuf[0] << 2 | iBuf[1] >> 4);
		oBuf[1]																= (iBuf[1] << 4 | iBuf[2] >> 2);
		oBuf[2]																= (((iBuf[2] << 6) & 0xc0) | iBuf[3]);
		
		[retValue appendBytes:oBuf length:inputParts - 1];
	}
	
	return retValue;
}

//
// url encode
//
- (NSString*)encodeURL:(NSStringEncoding)encoding
{
	NSString* retValue														= (NSString*)CFURLCreateStringByAddingPercentEscapes(0, (CFStringRef)self, 0, (CFStringRef)@";/?:@&=$+{}<>,", CFStringConvertNSStringEncodingToEncoding(encoding));
	return [retValue autorelease];
}

//
// url decoding
//
- (NSString*)decodeURL:(NSStringEncoding)encoding
{
	NSString* retValue														= (NSString*)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(0, (CFStringRef)self, CFSTR(""), CFStringConvertNSStringEncodingToEncoding(encoding));
	return [retValue autorelease];
}

//
// encode entity
//
- (NSString*)encodeEntity
{
	NSMutableString* retValue												= [NSMutableString stringWithString:self];
	[retValue replaceOccurrencesOfString:@"&" withString:@"&amp;" options:NSLiteralSearch range:NSMakeRange(0, retValue.length)];
	[retValue replaceOccurrencesOfString:@"\"" withString:@"&quot;" options:NSLiteralSearch range:NSMakeRange(0, retValue.length)];
	[retValue replaceOccurrencesOfString:@"'" withString:@"&#x27;" options:NSLiteralSearch range:NSMakeRange(0, retValue.length)];
	[retValue replaceOccurrencesOfString:@">" withString:@"&gt;" options:NSLiteralSearch range:NSMakeRange(0, retValue.length)];
	[retValue replaceOccurrencesOfString:@"<" withString:@"&lt;" options:NSLiteralSearch range:NSMakeRange(0, retValue.length)];
	return retValue;
}

//
// decode time
//
- (NSInteger)decodeTime
{
	NSError* error															= nil;
	NSRegularExpression* regex												= [NSRegularExpression regularExpressionWithPattern:@"^\\s*(?:(\\d+)\\s*days?)?\\s*(\\d+(?:\\:))?(\\d+)\\:(\\d+)\\s*$" options:NSRegularExpressionAnchorsMatchLines error:&error];
	NSTextCheckingResult* match												= error || !regex ? nil : [regex firstMatchInString:self options:0 range:NSMakeRange(0, self.length)];
	if(!match || match.numberOfRanges != 5)
		return 0;
	
	
	NSInteger retValue														= 0;
	NSRange range															= [match rangeAtIndex:1];
	if(range.length && range.location != NSNotFound)
		retValue															+= [[self substringWithRange:range] integerValue] * 24 * 60 * 60;
	
	range																	= [match rangeAtIndex:2];
	if(range.length && range.location != NSNotFound)
		retValue															+= [[self substringWithRange:range] integerValue] * 60 * 60;
	
	retValue																+= [[self substringWithRange:[match rangeAtIndex:3]] integerValue] * 60;
	retValue																+= [[self substringWithRange:[match rangeAtIndex:4]] integerValue];
	
	return retValue;
}

//
// format size/rate
//
+ (NSString*)formatSizeRate:(uint64_t)value isRate:(BOOL)isRate
{
	if(value < 1024 * 1024)
		return [NSString stringWithFormat:isRate ? @"%.2f KB/s" : @"%.2f KB", value / 1024.f];
	
	if(value < 1024 * 1024 * 1024)
		return [NSString stringWithFormat:isRate ? @"%.2f MB/s" : @"%.2f MB", value / 1024.f / 1024.f];
	
	return [NSString stringWithFormat:isRate ? @"%.2f GB/s" : @"%.2f GB", (float)(value / 1024.0 / 1024.0 / 1024.0)];
}

//
// format time
//
+ (NSString*)formatTime:(NSInteger)timeInSecond
{
	if(timeInSecond < 0)
		return NSLocalizedString(@"Inf.", nil);
	
	NSInteger second														= timeInSecond % 60;
	timeInSecond															/= 60;
	NSInteger minute														= timeInSecond % 60;
	timeInSecond															/= 60;
	NSInteger hour															= timeInSecond % 24;
	NSInteger day															= timeInSecond / 24;
	
	if(day)
		return [NSString stringWithFormat:NSLocalizedString(@"%dd %dh", nil), day, hour];

	if(hour)
		return [NSString stringWithFormat:NSLocalizedString(@"%dh %dm", nil), hour, minute];
	
	return [NSString stringWithFormat:NSLocalizedString(@"%dm %ds", nil), minute, second];
}

@end
